#ifndef __TUI__PAGE__
#define __TUI__PAGE__

#include "component.h"
class Drawer;
class Page;
class BaseItem;
class Containor;

struct ContainorAttr : ShapeAttr
{
    ContainorAttr() : ShapeAttr({1, 1}, {0, 0}, 'X', false) {}
    ContainorAttr(const Coord_t& pos, const Coord_t& size, char c) : ShapeAttr(pos, size, c, false) {}
    ~ContainorAttr() {}
    bool operator==(const ContainorAttr& b)
    {
        return (this->pos == b.pos) + (this->size == b.size) + (this->offset == b.offset) +
               (this->drawchar == b.drawchar) + (this->filled == b.filled);
    }
};

struct ContainorUpdaterInterface
{
  protected:
    using ContainorUDIF = ContainorUpdaterInterface;
    ContainorUpdaterInterface() {}
    ~ContainorUpdaterInterface() {}

    // Containor* base;

  public:
    virtual ContainorUDIF& Position(Coord_t) = 0;
    virtual ContainorUDIF& Size(Coord_t) = 0;
    virtual ContainorUDIF& BorderStyle(char) = 0;
    virtual ContainorUDIF& Offset(Coord_t) = 0;
    virtual Action_t Commit() = 0;
    virtual Action_t Rollback() = 0;

  protected:
};

class Containor : public Component, public ContainorUpdaterInterface
{
  public:
    Containor();
    Containor(Coord_t, Coord_t, char, Drawer*);
    Containor(Coord_t, Coord_t, char, Drawer*, Containor*);
    virtual ~Containor();
    // Component*& operator[](int i) { return this->_contain[i]; }
    // Component*& at(int i);

    void render() override;
    void bindDrawer(Drawer*) override;
    Action_t Zerolize() override;
    using LeftTop = Component;
    using RightTop = Component;
    using LeftBottom = Component;
    using RightBottom = Component;
    void Load(LeftTop*, RightTop*, LeftBottom*, RightBottom*);

    ContainorUDIF& Position(Coord_t) override;
    ContainorUDIF& Size(Coord_t) override;
    ContainorUDIF& BorderStyle(char) override;
    ContainorUDIF& Offset(Coord_t) override;
    Action_t Commit() override;
    Action_t Rollback() override;
    Action_t SetFather(Containor* fa) override;
    Component* getElement(int i) { return _contain[i]; }
    void clearElement(int the_socket_id_of_element)
    {
        // if (!this) printf("Warning: A NULL containor");
        // if (this == (Containor*)(0xbaadf00dbaadf00d)) printf("Warning: A Bad containor");
        if (_contain[the_socket_id_of_element]) _contain[the_socket_id_of_element] = nullptr;
    }
    void setElement(int i, Component* to) { _contain[i] = to; }

  protected:
    // Containor* father;
    using Socket = Component;
    void UpdateChildCoord(Socket* = nullptr, Socket* = nullptr, Socket* = nullptr, Socket* = nullptr) override;
    ContainorAttr attributes;
    ContainorAttr buffer;
    // Component* _contain[4];
    Component* _contain[4]{nullptr, nullptr, nullptr, nullptr};

  private:
    int containStatus{0};
};

class Page : public Containor
{
    Page();
    virtual ~Page();
    void render() override;
    // void set(Containor* Content, int i) override;
    // void add(Containor* Content) override;

  private:
    Drawer* ptr_drawer;
};

using Contained = CoordGroup;
struct Full
{
    Full(const Coord_t& fatherPos, const Coord_t& fatherSize) : Content(fatherPos.append(0, 0), fatherSize.append(0, 0))
    {
    }
    ~Full() {}

    // private:
    Contained Content;
};
struct UpDown
{
    UpDown(const Coord_t& fatherPos, const Coord_t& fatherSize, const Coord_t& offset = {0, 0})
    {
        Up.pos = fatherPos.append(0, 0);
        Up.size = {short(fatherSize.X), short(fatherSize.Y / 2)};
        Down.pos = Up.pos.append(0, Up.size.Y - 1);
        Down.size = {Up.size.X, short(fatherSize.Y - Up.size.Y + 1)}; // Up.size;
    }
    ~UpDown() {}

    // private:
    Contained Up;
    Contained Down;
};

struct LeftRight
{
    LeftRight(const Coord_t& fatherPos, const Coord_t& fatherSize, const Coord_t& offset = {0, 0})
    {
        Left.pos = fatherPos.append(0, 0);
        Left.size = {short(fatherSize.X / 2 + 1), short(fatherSize.Y)};
        Right.pos = Left.pos.append(Left.size.X - 1, 0);
        Right.size = {short(fatherSize.X - Left.size.X + 1), Left.size.Y}; // Left.size.append(-1, 0);
    }
    ~LeftRight() {}

    // private:
    Contained Left;
    Contained Right;
};
struct FourGrid
{
    FourGrid(const Coord_t& fatherPos, const Coord_t& fatherSize, const Coord_t& offset = {0, 0})
    {
        TopLeft.pos = fatherPos.append(0, 0);
        TopLeft.size = {short(fatherSize.X / 2 + 1), short(fatherSize.Y / 2)};
        TopRight.pos = TopLeft.pos.append(TopLeft.size.X - 1, 0);
        TopRight.size = {short(fatherSize.X - TopLeft.size.X + 1), TopLeft.size.Y};
        BottomLeft.pos = TopLeft.pos.append(0, TopLeft.size.Y - 1);
        BottomLeft.size = {TopLeft.size.X, short(fatherSize.Y - TopLeft.size.Y + 1)};
        BottomRight.pos = {TopRight.pos.X, BottomLeft.pos.Y};
        BottomRight.size = {TopRight.size.X, BottomLeft.size.Y};
    }
    // BottomRight.pos = BottomLeft.pos.append(BottomLeft.size.X, 0);
    // BottomRight.size = TopRight.size.append(0, 1 + TopLeft.pos.Y % 2);
    ~FourGrid() {}

    // private:
    Contained TopLeft;
    Contained TopRight;
    Contained BottomLeft;
    Contained BottomRight;
};
#endif